#include "snmpinc.h"

#if SNMP_WANTED==1
/****************************************************************************
Lcl_Open -- Open a buffer for use as a local I/O stream
Parameters: LCL_FILE *lfile
            _UINT8  *buffer
            _UINT16 nbytes
Returns: (LCL_FILE *) if sucessful, (LCL_FILE *)0 if unsucessful.
****************************************************************************/
LCL_FILE *Lcl_Open(LCL_FILE *lfile, _UINT8 *buff, _UINT16 nbytes)
{
	if(lfile == 0)
	{
		return 0;
	}
	lfile->lcl_flags = 0;
	lfile->lbuf_start = buff;
	lfile->lbuf_next = buff;
	lfile->lbuf_end = (_UINT8 *)(buff + nbytes);
	return (lfile);
}

/****************************************************************************
Lcl_Peekc -- Peek at a character from a local I/O stream, the seek poINT32er is not advanced.
Parameters: LCL_FILE *      lfile
Returns: If sucessful: the character read, but in INT32eger format
	If unsucessful: -1
****************************************************************************/
#if 0
_INT16 Lcl_Peekc(LCL_FILE *lfile)
{
	if(lfile->lcl_flags & LCL_EOF)
	{
		return -1;
	}
	if(lfile->lbuf_next < lfile->lbuf_end)
	{
		return (*(lfile->lbuf_next));
	}
	else
	{
		lfile->lcl_flags |= LCL_EOF;
		return -1;
	}
}
#endif
/****************************************************************************
Lcl_Read -- Read a set of characters from a local I/O stream.
Parameters:
  LCL_FILE *      lfile
  _UINT8  *      ubuf
  _UINT16       nbytes
Returns: The number of bytes actually read.
****************************************************************************/
_UINT16 Lcl_Read(LCL_FILE *lfile, _UINT8 *ubuf, _UINT16 nbytes)
{
	/* This is a quick implementation, to be replaced later */
	_UINT16 orig_nbytes = nbytes;
	_UINT8 c;
	while(nbytes > 0)
	{
		c = (_UINT8) Lcl_Getc(lfile);
		if(Lcl_Eof(lfile))
		{
			break;
		}
		*ubuf++ = c;
		--nbytes;
	}
	return (orig_nbytes - nbytes);
}

/****************************************************************************
Lcl_Seek -- Move the seek poINT32er to a give position in the local I/O buffer.
Parameters:
  LCL_FILE *      lfile
  _UINT16       offset
  _INT32             whence:
  0 to set poINT32er to offset bytes from the start
  1 to move poINT32er by offset bytes
  2 to set poINT32er to offset bytes from the end
Returns: 0 if sucessful, -1 if not.
Note: The "end" position is the byte AFTER the last one in the buffer
	  containing data.  Thus, a Lcl_Seek(.., 0, 2) will leave the caller at
	  the end-of-file.  The last byte is reached by Lcl_Seek(.., 1, 2).
****************************************************************************/
_INT16 Lcl_Seek(LCL_FILE *lfile, _UINT16 offset, _INT16 whence)
{
	_UINT8 *next;
	switch(whence)
	{
	case 0:
		next = (_UINT8 *)(lfile->lbuf_start + offset);
		break;
	case 1:
		next = (_UINT8 *)(lfile->lbuf_next + offset);
		break;
	case 2:
		next = (_UINT8 *)(lfile->lbuf_end - offset);
		break;
	default:
		return -1;
	}
	if((next < lfile->lbuf_start) || (next > lfile->lbuf_end))
	{
		return -1;
	}
	if(next < lfile->lbuf_end)
	{
		lfile->lcl_flags &= ~LCL_EOF;
	}
	lfile->lbuf_next = next;
	return 0;
}
#if 1
_UINT32 Uint32Get(VB_T *vbp)
{
	return (_UINT32)(vbp->value_u.v_counter);
}

_INT32  Int32Get(VB_T *vbp)
{
	return (_INT32)(vbp->value_u.v_number);
}
_UINT8   *octetGet(VB_T *vbp)
{
	return (_UINT8 *)(vbp->value_u.v_string);
}
_UINT32 *oidGet(VB_T *vbp)
{
	return (_UINT32 *)(vbp->value_u.v_object.component_list);
}

void Uint32Set(VB_T *vbp,_UINT32 value)
{
	vbp->vb_data_flags_n_type = VT_UNSIGNED32;
	vbp->value_u.v_counter=value;
}

void GaugeSet(VB_T *vbp,_UINT32 value)
{
	vbp->vb_data_flags_n_type = VT_GAUGE;
	vbp->value_u.v_counter=value;
}

void CounterSet(VB_T *vbp,_UINT32 value)
{
	vbp->vb_data_flags_n_type = VT_COUNTER;
	vbp->value_u.v_counter=value;
}

void Counter64Set(VB_T *vbp,_UINT32 high,_UINT32 low)
{
	vbp->vb_data_flags_n_type = VT_COUNTER64;
	vbp->value_u.v_counter64.high=high;
	vbp->value_u.v_counter64.low=low;
}
#endif
void Int32Set(VB_T *vbp,_INT32 value)
{
	vbp->vb_data_flags_n_type = VT_NUMBER;
	vbp->value_u.v_number=value;
}

void TimetickSet(VB_T *vbp,_UINT32 value)
{
	vbp->vb_data_flags_n_type = VT_TIMETICKS;
	vbp->value_u.v_counter=value;
}

void oidSet(VB_T *vbp,_UINT32 *pOid,_UINT16 length)
{
	_UINT16 i;
	vbp->vb_data_flags_n_type = VT_OBJECT;
	for(i=0; i<length; i++)
	{
		vbp->value_u.v_object.component_list[i] = pOid[i];
	}
	vbp->value_u.v_object.num_components = length;
}
void octetSet(VB_T *vbp,_UINT8 *pValue,_INT16 length)
{
	if(length>MAX_OCTET_LENGTH)
	{
		length=MAX_OCTET_LENGTH;
	}
	memset(vbp->value_u.v_string,0,sizeof(vbp->value_u.v_string));
	memcpy(vbp->value_u.v_string,pValue,length);
	vbp->vb_data_length=length;
	vbp->vb_data_flags_n_type = VT_STRING;
}
void IpAddrSet(VB_T *vbp,_UINT32 addr/*input host order*/)
{
	vbp->value_u.v_counter=htonl(addr);
	vbp->vb_data_flags_n_type = VT_IPADDRESS;
}
_UINT32 IpAddrGet(VB_T *vbp)/*return host order*/
{
	return ntohl(vbp->value_u.v_counter);
}

/*
	Compare two object identifiers with different lengths.
 * 	Returns -1, 0, or +1 depending whether o1 < o2, o1 == o2, or o1 > o2
 */

_INT16 oidcmp(_UINT16 n1, _UINT32 *idp1,_UINT16 n2,_UINT32 *idp2,_INT16 *matchLen)
{
	(*matchLen)=0;
	while((n1 > 0) && (n2 > 0))
	{
		if(*idp1 != *idp2)
		{
			return (*idp1 < *idp2) ? -1 : 1;
		}
		idp1++;
		idp2++;
		n1--;
		n2--;
		(*matchLen)++;
	}
	if(n1 == n2)
	{
		return 0;    /* OIDs are the same */
	}
	else if(n1 > n2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

void oidcpy(OBJ_ID_T *pDst,OBJ_ID_T *pSrc)
{
	memcpy(pDst->component_list,pSrc->component_list,
	       pSrc->num_components*sizeof(_UINT32));
	pDst->num_components=pSrc->num_components;
}

void oid_print(OBJ_ID_T *pOid)
{
	_UINT8 i;
	i=pOid->num_components;
	for(i=0; i<pOid->num_components; i++)
	{
		SNMP_DEBUG("%d.",pOid->component_list[i]);
	}
	SNMP_DEBUG("\r\n");
}
#endif

